package net.jiastudy.web.authentication;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import cn.hutool.core.util.StrUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import net.jiastudy.biz.user.service.UserService;
import net.jiastudy.core.common.SecurityConstant;
import net.jiastudy.core.exception.AccessDenidException;
import net.jiastudy.core.exception.ServiceException;

public class JWTAuthenticationFilter extends BasicAuthenticationFilter {

	private static Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);

	@SuppressWarnings("unused")
	private ApplicationContext context;
	private UserService userService;

	public JWTAuthenticationFilter(AuthenticationManager authenticationManager, ApplicationContext context) {
		super(authenticationManager);
		this.context = context;
		userService = context.getBean(UserService.class);
	}

	public JWTAuthenticationFilter(AuthenticationManager authenticationManager,
			AuthenticationEntryPoint authenticationEntryPoint, ApplicationContext context) {
		super(authenticationManager, authenticationEntryPoint);
		this.context = context;
		userService = context.getBean(UserService.class);
	}

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		String token = request.getHeader(SecurityConstant.HEADER);
		if (StrUtil.isBlank(token)) {
			token = request.getParameter(SecurityConstant.HEADER);
		}
		if (StrUtil.isBlank(token) || !token.startsWith(SecurityConstant.TOKEN_SPLIT)) {
			chain.doFilter(request, response);
			return;
		}

		UsernamePasswordAuthenticationToken authentication = getAuthentication(token);
		SecurityContextHolder.getContext().setAuthentication(authentication);

		chain.doFilter(request, response);
	}

	private UsernamePasswordAuthenticationToken getAuthentication(String token) {
		if (StrUtil.isNotBlank(token)) {
			// 解析token
			Claims claims = null;
			try {
				claims = Jwts.parser().setSigningKey(SecurityConstant.JWT_SIGN_KEY)
						.parseClaimsJws(token.replace(SecurityConstant.TOKEN_SPLIT, "")).getBody();

				// 获取用户名
				String username = claims.getSubject();

				String logintime = claims.get(SecurityConstant.LOGIN_TIME).toString();
				logger.debug("登录时间：" + logintime);

				// 获取权限
				List<GrantedAuthority> authorities = new ArrayList<>();
				if (StrUtil.isNotBlank(username)) {
					UserDetails user = userService.getUserByUsername(username);
					if (null == user) {
						throw new ServiceException("用户不存在");
					}
					return new UsernamePasswordAuthenticationToken(user, null, authorities);
				}
			} catch (ExpiredJwtException e) {
				throw new AccessDenidException("401", "登录已失效，请重新登录");
			}
		}
		return null;
	}

}